/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../impl/head.h"
#include "list_impl.h"

/////////////////////////////////////////////////////////////////////////////////////////
// 
namespace xos_box
{
    ////////////////////////////////////////////////////////////////////////////////////
    // 

    static list_impl::ITEM_DATA xos_item_data;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // list_impl

    list_impl::list_impl()
    {
        m_item_iter = m_item_list.begin();
    }

    list_impl::~list_impl()
    {
        term();
    }

    ////////////////////////////////////////////////////////////////////////////////////
    // 

    int list_impl::get_xos_item_data( ITEM_DATA *& item_ptr )
    {
        int ret = 0;
        xos_item_data.set_container( mgr::container() );
        item_ptr = &xos_item_data;
        return ret;
    }

    int list_impl::static_user_init()
    {
        int ret = 0;
        list_iter::init_all();
        return ret;
    }

    int list_impl::static_user_term()
    {
        int ret = 0;
        list_iter::term_all();
        return ret;
    }

    int list_impl::init()
    {
        int ret = 0;
        return ret;
    }

    int list_impl::term()
    {
        int ret = 0;
        release_all();
        m_item_iter = m_item_list.begin();
        return ret;
    }

    ////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // add / get data
    // 
    int list_impl::add_data( const char * lpszData, int nLen, bool bTail )
    {
        int ret = 0;
        int nPos = 0;
        if( size() > 0 )
        {
            i_buf * pBuf = 0;
            if( bTail )
            {
                pBuf = (i_buf *)back( 0 );
            }
            else
            {
                pBuf = (i_buf *)front( 0 );
            }
            int len = pBuf->add_data( lpszData, nLen, bTail );
            if( bTail )
            {
                nPos += len;
            }
            nLen -= len;
        }
        while( nLen > 0 )
        {
            i_buf * pBuf = mgr::container()->box()->buf();
            int nSize = pBuf->get_buf_size( 0 );
            int len = nSize > nLen ? nLen : nSize;
            if( bTail )
            {
                int pos = nPos;
                pBuf->add_data( lpszData + pos, len, true );
                push_back( pBuf );
                nPos += len;
            }
            else
            {
                int pos = nPos + nLen - len;
                pBuf->add_data( lpszData + pos, len, true );
                push_front( pBuf );
            }
            nLen -= len;
        }
        return ret;
    }

    int list_impl::add_data( i_big_buf * pBuf, bool bTail )
    {
        int ret = 0;
        int nLen = 0;
        const char * lpszBuf = pBuf->get_data( 0, 0, 0, &nLen );
        add_data( lpszBuf, nLen, bTail );
        return ret;
    }

    int list_impl::add_data( i_buf * pBuf, bool bTail )
    {
        int ret = 0;
        int nLen = 0;
        const char * lpszBuf = pBuf->get_data( 0, 0, 0, &nLen );
        add_data( lpszBuf, nLen, bTail );
        return ret;
    }

    int list_impl::add_str( const char * lpszStr, bool bTail )
    {
        int ret = 0;
        xos::i_crt * pCrt = mgr::container()->crt();
        int nLen = pCrt->strlen( lpszStr );
        add_data( lpszStr, nLen, bTail );
        return ret;
    }

    int list_impl::add_str( i_string * pStr, bool bTail )
    {
        int ret = 0;
        const char * lpszBuf = pStr->get( 0, 0 );
        int nLen = (int)pStr->length();
        add_data( lpszBuf, nLen, bTail );
        return ret;
    }

    ////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // ret : get data len
    // 
    int list_impl::get_data( char * lpszData, int nLen )
    {
        int ret = 0;
        int nPos = 0;
        while( ( nLen > 0 ) && ( size() > 0 ) )
        {
            i_buf * pBuf = (i_buf *)front( 0 );
            int nGet = 0;
            pBuf->get_data( lpszData + nPos, nLen, &nGet, 0 );
            nLen -= nGet;
            nPos += nGet;
            int len = pBuf->get_len( 0 );
            if( 0 == len )
            {
                xos_stl::release_interface( pBuf );
                pop_front();
            }
        }
        ret = nPos;
        return ret;
    }

    int list_impl::get_data( i_big_buf * pBuf )
    {
        int ret = 0;
        int nLen = 0;
        pBuf->move_data_to_begin();
        char * lpszBuf = pBuf->get_data( 0, 0, 0, &nLen );
        int nBuf = pBuf->get_buf_size( 0 ) - nLen;
        int nGet = get_data( lpszBuf + nLen, nBuf );
        nLen += nGet;
        pBuf->set_len( nLen );
        ret = nGet;
        return ret;
    }

    int list_impl::get_data( i_buf * pBuf )
    {
        int ret = 0;
        int nLen = 0;
        pBuf->move_data_to_begin();
        char * lpszBuf = pBuf->get_data( 0, 0, 0, &nLen );
        int nBuf = pBuf->get_buf_size( 0 ) - nLen;
        int nGet = get_data( lpszBuf + nLen, nBuf );
        nLen += nGet;
        pBuf->set_len( nLen );
        ret = nGet;
        return ret;
    }

    ////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // load/save file
    // 
    int list_impl::load( const char * lpszFile )
    {
        int ret = 0;
        xos::i_file * pFile = mgr::container()->xos()->file();
        xos_box::i_list * pList = this;
        if( 0 == ret )
        {
            ret = pFile->open( lpszFile, xos::i_file::XOS_FILE_READ, xos::i_file::XOS_SHARE_READ, xos::i_file::XOS_FILE_OPEN );
        }
        if( 0 == ret )
        {
            pFile->read( pList );
        }
        xos_stl::release_interface( pFile );
        return ret;
    }

    int list_impl::save( const char * lpszFile )
    {
        int ret = 0;
        xos::i_file * pFile = mgr::container()->xos()->file();
        xos_box::i_list * pList = this;
        if( 0 == ret )
        {
            ret = pFile->open( lpszFile, xos::i_file::XOS_FILE_WRITE, xos::i_file::XOS_SHARE_READ, xos::i_file::XOS_FILE_CREATE );
        }
        if( 0 == ret )
        {
            pFile->write( pList );
        }
        xos_stl::release_interface( pFile );
        return ret;
    }

    ////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // add back
    // 
    int list_impl::push_back( xos::i_release * pObj )
    {
        int ret = 0;
        m_item_list.push_back( pObj );
        return ret;
    }

    // 
    // return last, but not remove
    // 
    xos::i_release * list_impl::back( xos::i_release ** ppObj )
    {
        xos::i_release * pObj = 0;
        if( m_item_list.size() > 0 )
        {
            pObj = m_item_list.back();
        }
        if( ppObj )
        {
            *ppObj = pObj;
        }
        return pObj;
    }

    // 
    // pop back
    // 
    int list_impl::pop_back()
    {
        int ret = 0;
        m_item_list.pop_back();
        return ret;
    }

    // 
    // add front
    // 
    int list_impl::push_front( xos::i_release * pObj )
    {
        int ret = 0;
        m_item_list.push_front( pObj );
        return ret;
    }

    // 
    // return first, but not remove
    // 
    xos::i_release * list_impl::front( xos::i_release ** ppObj )
    {
        xos::i_release * pObj = 0;
        if( m_item_list.size() > 0 )
        {
            pObj = m_item_list.front();
        }
        if( ppObj )
        {
            *ppObj = pObj;
        }
        return pObj;
    }

    // 
    // pop front
    // 
    int list_impl::pop_front()
    {
        int ret = 0;
        m_item_list.pop_front();
        return ret;
    }

    // 
    // remove with xos::i_release *
    // 
    int list_impl::remove( xos::i_release * pObj )
    {
        int ret = 0;
        m_item_list.remove( pObj );
        return ret;
    }

    // 
    // point to next after remove.
    // 
    xos::i_release * list_impl::remove()
    {
        xos_list::ITEM_ITER iter = m_item_iter;
        xos::i_release * pRet = 0;
        if( iter != m_item_list.end() )
        {
            m_item_iter++;
            pRet = *iter;
            m_item_list.erase( iter );
        }
        return pRet;
    }

    // 
    // reset list iter
    // 
    int list_impl::reset()
    {
        m_item_iter = m_item_list.begin();
        return 0;
    }

    // 
    // null if to end
    // 
    xos::i_release * list_impl::next()
    {
        xos::i_release * pRet = 0;
        if( m_item_iter != m_item_list.end() )
        {
            pRet = *m_item_iter++;
        }
        return pRet;
    }

    // 
    // 得到list的前后向迭代器
    // 
    i_list_iter * list_impl::rbegin()
    {
        list_iter * pRet = 0;
        xos_stl::init_pool_item( pRet );
        pRet->set( &m_item_list, false );
        pRet->init();
        return pRet;
    }

    i_list_iter * list_impl::begin()
    {
        list_iter * pRet = 0;
        xos_stl::init_pool_item( pRet );
        pRet->set( &m_item_list, true );
        pRet->init();
        return pRet;
    }

    // 
    // list operation
    // 
    int list_impl::add_to_front( xos_box::i_list * pList )
    {
        int ret = 0;
        while( xos::i_release * pUnk = pList->front( 0 ) )
        {
            pList->pop_front();
            push_front( pUnk );
        }
        return ret;
    }

    int list_impl::add_to_tail( xos_box::i_list * pList )
    {
        int ret = 0;
        while( xos::i_release * pUnk = pList->front( 0 ) )
        {
            pList->pop_front();
            push_back( pUnk );
        }
        return ret;
    }

    int list_impl::swap( xos_box::i_list * pList )
    {
        int ret = 0;
        list_impl * pListImpl = (list_impl *)pList;
        m_item_list.swap( pListImpl->m_item_list );
        return ret;
    }

    int list_impl::copy( xos_box::i_list * pList )
    {
        int ret = 0;
        i_list_iter * pIter = pList->begin();
        while( xos::i_release * pUnk = pIter->next() )
        {
            xos_box::i_buf * pDstBuf = mgr::container()->box()->buf();
            xos_box::i_buf * pSrcBuf = (xos_box::i_buf *)pUnk;
            pDstBuf->add_data( pSrcBuf, true );
            push_back( pDstBuf );
        }
        xos_stl::release_interface( pIter );
        return ret;
    }

    // 
    // release all
    // 
    int list_impl::release_all()
    {
        int ret = 0;
        m_item_list.release_all();
        return ret;
    }

    // 
    // remove all
    // 
    int list_impl::clear()
    {
        int ret = 0;
        m_item_list.clear();
        return ret;
    }

    // 
    // list item num
    // 
    int list_impl::size()
    {
        return (int)m_item_list.size();
    }

    // 
    // unlock/lock
    // 
    int list_impl::un_lock()
    {
        int ret = 0;
        m_item_list.un_lock();
        return ret;
    }

    // 
    // unlock/lock
    // 
    int list_impl::lock()
    {
        int ret = 0;
        m_item_list.lock();
        return ret;
    }
} // xos
